#include "cryptotool.h"

#include "openssl/testfunctions.h"

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/mem.h>
#include <gmssl/sm2.h>

struct {
  CryptoTool::CryptoType type;
  const char* desc;
} Crypto_Descs[] = {
    { CryptoTool::CryptoSM2Encrypt,  ""},
    { CryptoTool::CryptoSM2Decrypt,
        "Decrypt SM2-encrypted data using specific key: \n"
        "the key must be in pem format                  \n"
        "in and out represent input and output data     \n"
    },
    { CryptoTool::CryptoSM2ZEncrypt, ""},
    { CryptoTool::CryptoSM2ZDecrypt, ""},
    { CryptoTool::CryptoSM2Verify,   ""},
    { CryptoTool::CryptoSM2Sign,     ""},
    { CryptoTool::CryptoSM3Digest,   ""},
    { CryptoTool::CryptoSM3HMac,     ""},
    };


CryptoTool::CryptoTool() {}

void CryptoTool::SM2Encrypt(
    const char* pub_key_path,
    const uint8_t* in,
    size_t in_len,
    uint8_t* out,
    size_t* out_len) {

}

void CryptoTool::SM2Decrypt(const char* priv_key_path,
    const uint8_t* in,
    size_t in_len,
    uint8_t* out,
    size_t* out_len) {
  FILE* fp = fopen(priv_key_path, "rb");
  do {
    if(!fp) {
      printError("failed to open private key!");
      break ;
    }

    SM2_KEY sm2_key;
    if(sm2_private_key_info_from_pem(&sm2_key, fp) <= 0) {
      printError("failed to reading private key!");
      break;
    }

    SM2_DEC_CTX sm2_dec_ctx;
    if (sm2_decrypt_init(&sm2_dec_ctx) != 1) {
      printError("gmssl : sm2_decrypt_init failed\n");
      break;
    }

    if (sm2_decrypt_update(&sm2_dec_ctx, in, in_len) != 1) {
      printError("gmssl : sm2_decyrpt_update failed\n");
      break;
    }

    if (sm2_decrypt_finish(&sm2_dec_ctx, &sm2_key, out, out_len) != 1) {
      fprintf(stderr, "gmssl decryption failure\n");
      break;
    }

  } while(0);
  if(fp)
    fclose(fp);
}


void CryptoTool::SM2ZEncrypt()
{

}

void CryptoTool::SM2ZDecrypt()
{

}

void CryptoTool::SM2Sign()
{

}

void CryptoTool::SM2Verify()
{

}

void CryptoTool::SM3Digest()
{

}

void CryptoTool::SM3HMac()
{

}

const char *CryptoTool::GetDesc(CryptoType type) {
  return Crypto_Descs[type].desc;
}
